﻿using Quartz.Util;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;

namespace DoNet.Common.Helpers
{
    /// <summary>
    /// 
    /// </summary>
    public class TokenHelper
    {
        /// <summary>
        /// 生成token
        /// </summary>
        /// <param name="appId"></param>
        /// <param name="secretKey"></param>
        /// <param name="expireIn"></param>
        /// <param name="claims"></param>
        /// <returns></returns>
        public static string GenerateToken(string appId, string secretKey, int expireIn, Dictionary<string, string> claims)
        {
            var payload = new StringBuilder();
            payload.Append($"appid={appId}|exp={DateTime.UtcNow.AddMinutes(expireIn).Ticks}");

            foreach (var claim in claims)
            {
                payload.Append($"|{Convert.ToBase64String(Encoding.UTF8.GetBytes($"{claim.Key}={claim.Value}"))}");
            }

            using var hmac = new HMACSHA512(Encoding.UTF8.GetBytes(secretKey));
            var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(payload.ToString())));

            return $"{Convert.ToBase64String(Encoding.UTF8.GetBytes(payload.ToString()))}.{signature}";
        }

        /// <summary>
        /// 获取token中的 payload 、 Signature 和 Claims 
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static Tuple<string, string, Dictionary<string, string>> GetParseClaims(string token, bool isExp = false)
        {
            string payload = string.Empty;
            string signature = string.Empty;
            var claims = new Dictionary<string, string>();
            var parts = GetPartArray(token);
            if (parts != null)
            {
                payload = parts[0];
                signature = parts[1];
                var claimsArray = Encoding.UTF8.GetString(Convert.FromBase64String(payload)).Split('|');
                if (claimsArray.Length > 2)
                {
                    int i = 0;
                    foreach (var pair in claimsArray)
                    {
                        if (i >= 2)
                        {
                            var kv = Encoding.UTF8.GetString(Convert.FromBase64String(pair)).Split('=');
                            //payload.Append($"|{claim.Key}={Convert.ToBase64String(Encoding.UTF8.GetBytes(claim.Value))}");
                            claims[kv[0]] = kv[1];
                        }
                        else
                        {
                            if(isExp)
                            {
                                var kv = pair.Split('=');
                                claims[kv[0]] = kv[1];
                            }
                        }
                        i++;
                    }
                }
            }
            return new Tuple<string, string, Dictionary<string, string>>(payload, signature, claims);
        }

        /// <summary>
        /// 获取token中的 Claims
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static string[]? GetPartArray(string token)
        {
            var claims = new Dictionary<string, string>();
            if (!string.IsNullOrEmpty(token))
            {
                var parts = token.Split('.');
                if (parts != null)
                {
                    if (parts.Length == 2)
                    {
                        return parts;
                    }
                }
            }
            return default;
        }
    }
}
